package com.local.web.service.impl;

import com.local.cart.pojo.ShoppingCart;
import com.local.common.constants.BusinessException;
import com.local.common.constants.ExceptionCodeEnum;
import com.local.common.util.NumberUtil;
import com.local.common.util.PageResultUtil;
import com.local.common.util.ResultUtil;
import com.local.coupon.feign.CouponServiceFeign;
import com.local.coupon.pojo.Coupon;
import com.local.coupon.pojo.UserCouponRecord;
import com.local.goods.feign.GoodsServiceFeign;
import com.local.goods.pojo.Goods;
import com.local.order.feign.OrderServiceFeign;
import com.local.order.pojo.Order;
import com.local.order.pojo.OrderItem;
import com.local.order.pojo.OrdersRequestParam;
import com.local.user.pojo.User;
import com.local.web.service.OrderService;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;


@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private GoodsServiceFeign goodsServiceFeign;

    @Autowired
    private OrderServiceFeign orderServiceFeign;

    @Autowired
    private CouponServiceFeign couponServiceFeign;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Value("${rabbitmq.order-exchange}")
    private String orderExchange;

    @Value("${rabbitmq.order-unpay-routingKey}")
    private String orderUnpayRoutingKey;

    @Value("${rabbitmq.order-unpay-queue-expiration-time}")
    private String orderUnpayQueueExpirationTime;

    @Value("${rabbitmq.used-user-coupon-record-exchange}")
    private String usedUserCouponRecordExchange;

    @Value("${rabbitmq.used-user-coupon-record-routingkey}")
    private String usedUserCouponRecordRoutingKey;

    @Value("${rabbitmq.cart-delete-exchange}")
    private String cartDeleteExchange;

    @Value("${rabbitmq.cart-delete-routingkey}")
    private String cartDeleteRoutingKey;


    /**
     * 生成订单
     * @param user
     * @param shoppingCartList
     * @param userCouponRecordId
     * @return
     */
    @Override
    public String saveOrder(User user, List<ShoppingCart> shoppingCartList, Integer userCouponRecordId) {
        List<Integer> goodsIdList = shoppingCartList.stream().map(ShoppingCart::getGoodsId).collect(Collectors.toList());

        ResultUtil<List<Goods>> goodsListResult = goodsServiceFeign.getGoodsListByIds(goodsIdList);
        if (Objects.isNull(goodsListResult)) {
            throw new BusinessException(ExceptionCodeEnum.BUSINESS_EXCEPTION.getCode(), ExceptionCodeEnum.BUSINESS_EXCEPTION.getMessage());
        }
        if (goodsListResult.getCode() != 200) {
            throw new BusinessException(goodsListResult.getCode(), goodsListResult.getMessage());
        }
        List<Goods> goodsList = goodsListResult.getData();

        //将goodslist转成goodsmap
        Map<Integer, Goods> goodsMap = goodsList.stream().collect(Collectors.toMap(Goods::getGoodsId, Function.identity(), (entity1, entity2) -> entity1));

        //检查商品状态和库存
        Integer priceTotal = 0;//订单总价
        for (int i = 0; i < shoppingCartList.size(); i++) {
            ShoppingCart shoppingCart = shoppingCartList.get(i);
            if (!goodsMap.containsKey(shoppingCart.getGoodsId())) {
                //商品集合中不存在购物车中的某商品，则从移除购物车移除该商品
                shoppingCartList.remove(i);
                continue;
            }
            if (goodsMap.get(shoppingCart.getGoodsId()).getGoodsSellStatus() != 0) {
                //商品已下架，则从移除购物车移除该商品
                shoppingCartList.remove(i);
                continue;
            }

            if (shoppingCart.getGoodsCount() > goodsMap.get(shoppingCart.getGoodsId()).getStockNum()) {
                //某商品库存不足，请提示返回购物车修改
                throw new BusinessException(
                        ExceptionCodeEnum.ORDER_GOODS_STOCK_NUM_NOT_ENOUGH.getCode(),
                        goodsMap.get(shoppingCart.getGoodsId()).getGoodsName() + ExceptionCodeEnum.ORDER_GOODS_STOCK_NUM_NOT_ENOUGH.getMessage()
                );
            }

            //计算订单总价
            priceTotal += shoppingCart.getSellingPrice() * shoppingCart.getGoodsCount();
        }

        //如果使用了优惠券，对总价进行折扣
        if (Objects.nonNull(userCouponRecordId) && userCouponRecordId > 0) {
            //通过userCouponRecordId查询相应数据记录
            ResultUtil<UserCouponRecord> userCouponRecordResult = couponServiceFeign.getUserCouponRecordById(userCouponRecordId);
            if (Objects.isNull(userCouponRecordResult)) {
                throw new BusinessException(ExceptionCodeEnum.BUSINESS_EXCEPTION.getCode(), ExceptionCodeEnum.BUSINESS_EXCEPTION.getMessage());
            }
            if (userCouponRecordResult.getCode() != 200) {
                throw new BusinessException(userCouponRecordResult.getCode(), userCouponRecordResult.getMessage());
            }
            UserCouponRecord userCouponRecord = userCouponRecordResult.getData();

            ResultUtil<Coupon> couponResult = couponServiceFeign.getCouponById(userCouponRecord.getCouponId());
            if (Objects.isNull(couponResult)) {
                throw new BusinessException(ExceptionCodeEnum.BUSINESS_EXCEPTION.getCode(), ExceptionCodeEnum.BUSINESS_EXCEPTION.getMessage());
            }
            if (couponResult.getCode() != 200) {
                throw new BusinessException(couponResult.getCode(), couponResult.getMessage());
            }
            Coupon coupon = couponResult.getData();
            priceTotal -= coupon.getDiscount();
        }
        if (priceTotal <= 0) {
            //订单价格异常，请重新检查
            throw new BusinessException(
                    ExceptionCodeEnum.ORDER_TOTAL_PRICE_ERROR.getCode(),
                    ExceptionCodeEnum.ORDER_TOTAL_PRICE_ERROR.getMessage()
            );
        }

        //生成订单 - 远程调用order-service接口
        Order order = new Order();
        order.setUserId(user.getUserId());
        order.setUserAddress(user.getAddress());
        order.setTotalPrice(priceTotal);
        ResultUtil<Order> orderSaveResult = orderServiceFeign.saveOrder(order);
        if (Objects.isNull(orderSaveResult)) {
            throw new BusinessException(ExceptionCodeEnum.BUSINESS_EXCEPTION.getCode(), ExceptionCodeEnum.BUSINESS_EXCEPTION.getMessage());
        }
        if (orderSaveResult.getCode() != 200) {
            throw new BusinessException(orderSaveResult.getCode(), orderSaveResult.getMessage());
        }
        Order orderNew = orderSaveResult.getData();
        Integer orderId = orderNew.getOrderId();
        String orderNo = orderNew.getOrderNo();

        //生成orderItem数据
        String dateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        List<OrderItem> orderItemList = new ArrayList<>();
        //修改商品库存
        List<Goods> goodsStockNumList = new ArrayList<>();
        for (ShoppingCart shoppingCart : shoppingCartList) {
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderId(orderId);
            orderItem.setSeckillId(0);
            orderItem.setGoodsId(shoppingCart.getGoodsId());
            orderItem.setGoodsName(shoppingCart.getGoodsName());
            orderItem.setGoodsCoverImg(shoppingCart.getGoodsCoverImg());
            orderItem.setSellingPrice(shoppingCart.getSellingPrice());
            orderItem.setGoodsCount(shoppingCart.getGoodsCount());
            orderItem.setCreateTime(dateTime);
            orderItemList.add(orderItem);

            Goods goods = new Goods();
            goods.setGoodsId(shoppingCart.getGoodsId());
            goods.setStockNum(shoppingCart.getGoodsCount());
            goods.setUpdateUser(user.getUserId());
            goods.setUpdateTime(dateTime);
            goodsStockNumList.add(goods);
        }
        ResultUtil<String> saveResult = orderServiceFeign.saveOrderItems(orderItemList);
        if (Objects.isNull(saveResult)) {
            throw new BusinessException(ExceptionCodeEnum.BUSINESS_EXCEPTION.getCode(), ExceptionCodeEnum.BUSINESS_EXCEPTION.getMessage());
        }
        if (saveResult.getCode() != 200) {
            throw new BusinessException(saveResult.getCode(), saveResult.getMessage());
        }

        //修改商品库存
        ResultUtil<String> updateGoodsStockNumResult = goodsServiceFeign.updateGoodsStockNum(goodsStockNumList);
        if (Objects.isNull(updateGoodsStockNumResult)) {
            throw new BusinessException(ExceptionCodeEnum.BUSINESS_EXCEPTION.getCode(), ExceptionCodeEnum.BUSINESS_EXCEPTION.getMessage());
        }
        if (updateGoodsStockNumResult.getCode() != 200) {
            throw new BusinessException(updateGoodsStockNumResult.getCode(), updateGoodsStockNumResult.getMessage());
        }

        //通过队列删除购物车相关数据
        //将id连接成字符串："1,2,3"
        String shoppingCartItemIds = shoppingCartList.stream()
                .map(shoppingCart -> shoppingCart.getCartItemId().toString())
                .collect(Collectors.joining(","));
        //将id字符串加入队列
        rabbitTemplate.convertAndSend(this.cartDeleteExchange, this.cartDeleteRoutingKey, shoppingCartItemIds);


        //通过队列更新优惠券的使用状态
        if (Objects.nonNull(userCouponRecordId) && userCouponRecordId > 0) {
            //将id加入队列
            rabbitTemplate.convertAndSend(this.usedUserCouponRecordExchange, this.usedUserCouponRecordRoutingKey, userCouponRecordId+","+orderId);
        }

        //将订单号orderNo发给消息队列，超过30分未支付自动取消订单......
        rabbitTemplate.convertAndSend(this.orderExchange, this.orderUnpayRoutingKey, orderNo, new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //设置消息有效时间30分钟，过期则自动进入dead letter死信消息队列
                //message.getMessageProperties().setExpiration("50000"); //20秒，测试
                message.getMessageProperties().setExpiration(orderUnpayQueueExpirationTime);
                return message;
            }
        });

        return orderNo;
    }

    @Override
    public ResultUtil<Order> getOrderByOrderNo(String orderNo) {
        ResultUtil<Order> detail = orderServiceFeign.detail(orderNo);
        return detail;
    }


    /**
     * 前台用户订单列表页，支持翻页
     * @param requestParam
     * @return
     */
    @Override
    public ResultUtil<PageResultUtil<Order>> orders(OrdersRequestParam requestParam) {
        ResultUtil<PageResultUtil<Order>> orders = orderServiceFeign.orders(requestParam);
        return orders;
    }
}
